import _mergeWith from 'lodash/mergeWith';
class Htool {
  // 生成uuid
  static genUuid() {
    const NUM1 = 16;
    const NUM2 = 0x3;
    const NUM3 = 0x8;
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      const r = (Math.random() * NUM1) | 0, v = c === 'x' ? r : (r & NUM2) | NUM3;
      return v.toString(NUM1);
    });
  };
  // 防抖函数
  static debounce(fn, delay) {
    let timer = null;
    return function (...args) {
      if (timer) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          fn(...args);
        }, delay);
      } else {
        timer = setTimeout(() => {
          fn(...args);
        }, delay);
      }
    }
  };
  // 节流函数
  static throttle(fn, delay) {
    let valid = true;
    return function (...args) {
      if (!valid) {
        return false;
      }
      valid = false; //防止他人执行
      fn(...args); // 直接执行函数
      setTimeout(() => {
        valid = true; // 延迟时间过后打开锁
      }, delay);
    };
  };
  // 深度拷贝对象,可以拷贝Vue的监听
  static extendObject(...args) {
    const {length} = args;// 仿写extendObject方法
    let i = 1;
    const newArguments = [];
    let deep = false;// 是否深拷贝
    let target = args[0];// 合并目标对象
    if (typeof target === 'boolean') {// 第一个值为布尔值代表是否深拷贝
      deep = target;
      target = args[1] || {};
      i = 2;
    }
    if (typeof target !== 'object' && typeof target !== 'function') {// 兼容处理
      target = {};
    }
    if (length === i) {// 如果只有一个对象，直接返回
      return target;
    }
    // 给予一个新的接受参数的对象
    for (i; i < length; i += 1) {
      newArguments.push(args[i]);
    }
    if (deep) {// 深浅拷贝的不同处理
      _mergeWith(target, ...newArguments, (objValue, srcValue, key, object) => {// 需要动态监听必须深拷贝一次该对象
        if (target.filterCopyKey && target.filterCopyKey.includes(key)) {
          return srcValue;
        }
        if (!Object.keys(object).includes(key)) {// 如果没有该key值，则强行使用set创建该key值的监听
          Vue.set(object, key);
        }
      });
    } else {
      target = Object.assign({}, target, ...newArguments);// 不用深拷贝直接使用Object.assign
    }
    return target;
  }
  // 并发promise控制的函数
  static concurrencyRequest(promiseArr, maxNum) {
    return new Promise((resolve, reject) => {
      if (promiseArr.length === 0) {
        resolve([]);
        return;
      }
      const results = [];
      let index = 0; // 下一个请求的下标
      let count = 0; // 当前请求完成的数量
      let rejectLock = false; // 出现错误时的锁
      async function request() {
        if (index === promiseArr.length || rejectLock) {
          return;
        }
        const i = index; // 保存序号，使result和promiseArr相对应
        const {func, args} = promiseArr[index];
        index++;
        try {
          results[i] = await func(...args);
        } catch (err) {
          rejectLock = true;
          reject();
        } finally {
          count++;
          // 判断是否所有的请求都已完成
          if (count === promiseArr.length) {
            resolve(results);
          }
          request();
        }
      }
      // maxNum和promiseArr.length取最小进行调用
      const times = Math.min(maxNum, promiseArr.length);
      for (let i = 0; i < times; i++) {
        request();
      }
    });
  };
  // 原生的下载文件操作
  static getDataByUrl(url, xhr, type, processCallback) {
    return new Promise((resolve, reject) => {
      const xhrObj = xhr || new XMLHttpRequest();
      xhrObj.open('GET', url);
      xhrObj.responseType = type
      xhrObj.onload = () => {
        resolve(xhrObj.response);
      };
      xhrObj.onprogress = e => {
        const percent = Math.floor((e.loaded / e.total) * Number('100'))
        processCallback && processCallback(e, percent)
      }
      xhrObj.onerror = e => {
        reject(e);
      };
      xhrObj.send();
    });
  };
}